package com.chenxbook.modules.jbpm4.assign;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.hibernate.Session;
import org.jbpm.api.Execution;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.HistoryService;
import org.jbpm.api.TaskService;
import org.jbpm.api.cmd.Command;
import org.jbpm.api.cmd.Environment;
import org.jbpm.api.task.Task;
import org.jbpm.pvm.internal.history.model.HistoryActivityInstanceImpl;

import java.util.List;
import java.util.Set;

/**
 * <p>className: JumpTaskCommand</p>
 * <p>description: 取回命令</p>
 *
 * <br>
 *
 * @author chenxbook
 * @version 1.0.0
 * @date 2020-05-24 16:42
 */
@Slf4j
public class WithdrawTaskCommand  implements Command<Void> {

    /**
     * 流程实例ID
     * */
    private String pid;
    /**
     * 取回目的地活动名称
     * */
    private String withdrawToActName;

    public WithdrawTaskCommand(String pid, String withdrawToActName) {
        this.pid = pid;
        this.withdrawToActName = withdrawToActName;
    }

    @Override
    public Void execute(Environment environment) throws Exception {
        //从流程引擎环境中获取执行、任务、历史3种服务
        ExecutionService executionService = environment.get(ExecutionService.class);
        TaskService taskService = environment.get(TaskService.class);
        HistoryService historyService = environment.get(HistoryService.class);
        //由于jBPM4没有清除历史数据的服务API直接提供，所以我们需要Hibernate Session对象直接操作持久层
        Session session = environment.get(Session.class);
        //获取当前活动名称集合
        Execution exec = executionService.findExecutionById(pid);
        Set<String> actNames = exec.findActiveActivityNames();
        if (actNames == null || actNames.size() == 0) {
            String msg = "没有可以取回的活动";
            log.error(msg);
            throw new Exception(msg);
        }
        if (actNames.size() > 1) {
            String msg = "存在多个活动的节点";
            log.error(msg);
            throw new Exception(msg);
        }
        String actName = actNames.iterator().next();
        String withdrawPath = actName + " to " + withdrawToActName;
        //获取当前活动的任务
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(pid).activityName(actName).list();
        if (CollectionUtils.isNotEmpty(tasks)) {
            for (Task task : tasks) {
                //结束任务（即取回任务）。如果任务执行失败，很可能是因为withdrawPath不存在，这说明当前活动已非取回目的地活动的下一步了
                taskService.completeTask(task.getId(), withdrawPath);
            }
            //在这里清除当前活动的历史痕迹，即删除历史活动实例及其历史任务
            HistoryActivityInstanceImpl histActInst = (HistoryActivityInstanceImpl)historyService
                    .createHistoryActivityInstanceQuery().activityName(actName).executionId(pid).uniqueResult();
            //使用Hibernate Session对象直接操作持久层
            session.delete(histActInst);
        }
        return null;
    }
}
